/* 
 * File:   common.cpp
 * Author: Satan
 * 
 * Created on September 9, 2012, 7:13 PM
 */

#include "hfgl/hfgl_point.h"
#include "common.h"

#include <windows.h>
#include <GL/glut.h> 

void CALLBACK vertexCallback(GLvoid* vertex) 
{ 
    const xypoint* pointer = (xypoint*)vertex; 
    std::vector<PolnayaHueta>* vecpoints = (std::vector<PolnayaHueta>*)pointer->ptr;
    (vecpoints->at(vecpoints->size()-1)).hueta.push_back(pointer->point);

//    DEBUG_OUT("HOLLY SHIT!!!!!!!!!   " << pointer->point.x << " : " << pointer->point.y);
} 

void CALLBACK errorCallback(GLenum errorCode) 
{ 
    const GLubyte *estring = gluErrorString(errorCode); 
    DEBUG_OUT("ERROR: " << estring); 
} 

void CALLBACK beginCallback(GLenum which, GLvoid* userdata) 
{ 
    std::vector<PolnayaHueta>* vecpoints = (std::vector<PolnayaHueta>*)userdata;
    vecpoints->push_back(PolnayaHueta(which, std::vector<hfgl_point>()));
} 

void CALLBACK combineData(GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, void* user_data) 
{ 
    std::vector<PolnayaHueta>* ret = (std::vector<PolnayaHueta>*)user_data;

    xypoint *toOut;
    toOut =  (xypoint*)malloc(sizeof(xypoint));
    toOut->point.x = coords[0];
    toOut->point.y = coords[1];
    toOut->ptr = ret;

    *outData = toOut;    

//    DEBUG_OUT("HOLLY SHIT!!!!!!!!!   ");
} 

common::common() 
{
}

common::common(const common& orig) 
{
}

common::~common() 
{
}

std::string common::xml_getAttribute(TiXmlElement* pElem, std::string attrName)
{
    if (!pElem->Attribute(attrName.c_str()))
        throw svg_exception(ENG_OBJECT_FILE_WRONG_ERROR, std::string(" No attribute \"" + attrName + "\".").c_str());
    
    return pElem->Attribute(attrName.c_str());
}

//std::vector<engpoint>* common::tesselation(std::vector<engpoint>* surface)
std::vector<PolnayaHueta>* common::tesselation(std::vector<hfgl_point>* surface)
{
//    std::vector<engpoint>* ret = new std::vector<engpoint>();
    std::vector<PolnayaHueta>* ret = new std::vector<PolnayaHueta>();
    
    GLUtesselator* tess = NULL;
    tess = gluNewTess();

    gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)vertexCallback); 
    gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)beginCallback); 
    gluTessCallback(tess, GLU_TESS_END, NULL); 
    gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr)errorCallback); 
    gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)combineData); 

    GLuint startList=glGenLists(2);
    GLdouble* coords = NULL;
    xypoint* ptrs = NULL;
            
    coords = new GLdouble[3 * surface->size()];
    ptrs = new xypoint[surface->size()];
    
    glNewList(startList,GL_COMPILE); 
        glShadeModel(GL_FLAT); 
        gluTessBeginPolygon(tess, ret); 
            gluTessBeginContour(tess); 
            int i = 0;
                for(std::vector<hfgl_point>::iterator it =  surface->begin(); it != surface->end(); it++)
                {
                    coords[(3 * i)] = (*it).x;
                    coords[(3 * i) + 1] = (*it).y;
                    coords[(3 * i) + 2] = 0;
                    
                    ptrs[i].point = (*it);
                    ptrs[i].ptr = ret;

                    gluTessVertex(tess, &coords[i * 3], &ptrs[i]);
                    i++;
                };
            gluTessEndContour(tess); 
        gluTessEndPolygon(tess); 
    glEndList();     
    
    gluDeleteTess(tess);
    tess = NULL;
    delete[] coords;
    delete[] ptrs;
    
    return ret;
}